Bug 557266 - Window Management Problem
authorTor Lillqvist <tml@novell.com>
Tue, 21 Oct 2008 20:31:05 +0000 (20:31 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Tue, 21 Oct 2008 20:31:05 +0000 (20:31 +0000)
2008-10-21  Tor Lillqvist  <tml@novell.com>

Bug 557266 - Window Management Problem

Also reported in mail to gtk-list, and of course it has been well
known in general that window state management is messy and buggy
in various ways in gdk/win32.

* gdk/win32/gdkwindow-win32.c (show_window_internal): Correct
handling of GDK_WINDOW_STATE_ABOVE windows. It doesn't work to set
the WS_EX_TOPMOST extended style bit using SetWindowLong(). We
must call SetWindowPos() on the window using HWND_TOPMOST
instead. The description for WS_EX_TOPMOST in the documentation
for CreateWindowEx() even implies that if you read it carefully.

svn path=/trunk/; revision=21694

ChangeLog
gdk/win32/gdkwindow-win32.c

index 79e8e19c8405eb23911051606e76b2bc8578d3d5..827bbb1db2a9e155a2cf86ebb2c3ad9d32f91c62 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2008-10-21  Tor Lillqvist  <tml@novell.com>
+
+       Bug 557266 - Window Management Problem
+
+       Also reported in mail to gtk-list, and of course it has been well
+       known in general that window state management is messy and buggy
+       in various ways in gdk/win32.
+
+       * gdk/win32/gdkwindow-win32.c (show_window_internal): Correct
+       handling of GDK_WINDOW_STATE_ABOVE windows. It doesn't work to set
+       the WS_EX_TOPMOST extended style bit using SetWindowLong(). We
+       must call SetWindowPos() on the window using HWND_TOPMOST
+       instead. The description for WS_EX_TOPMOST in the documentation
+       for CreateWindowEx() even implies that if you read it carefully.
+
 2008-10-21  Michael Natterer  <mitch@imendio.com>
 
        * gdk/gdkapplaunchcontext.c: reorder functions to be in standard
index 14f5129a2c7f94cfb9aa5fcfb2229bc641cff08a..340cc2a06370c70eaff84daa46e3354be9ce784f 100644 (file)
@@ -1028,6 +1028,8 @@ show_window_internal (GdkWindow *window,
   GdkWindowObject *private;
   HWND old_active_window;
   gboolean focus_on_map = TRUE;
+  DWORD exstyle;
+  HWND top;
 
   private = (GdkWindowObject *) window;
 
@@ -1078,35 +1080,38 @@ show_window_internal (GdkWindow *window,
       focus_on_map = private->focus_on_map;
     }
 
+  exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
+
+  if (private->state & GDK_WINDOW_STATE_BELOW)
+    exstyle &= (~WS_EX_TOPMOST);
+
+  if (private->state & GDK_WINDOW_STATE_ABOVE)
+    exstyle |= WS_EX_TOPMOST;
+
+  if (exstyle & WS_EX_TOPMOST)
+    top = HWND_TOPMOST;
+  else
+    top = HWND_TOP;
+
   /* Use SetWindowPos to show transparent windows so automatic redraws
    * in other windows can be suppressed.
    */
-  if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
+  if (exstyle & WS_EX_TRANSPARENT)
     {
       UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE;
+
       if (!raise)
        flags |= SWP_NOZORDER;
       if (!raise || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
        flags |= SWP_NOACTIVATE;
 
-      SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOP, 0, 0, 0, 0, flags);
+      SetWindowPos (GDK_WINDOW_HWND (window), top, 0, 0, 0, 0, flags);
+
       return;
     }
 
   old_active_window = GetActiveWindow ();
 
-  if (private->state & (GDK_WINDOW_STATE_BELOW | GDK_WINDOW_STATE_ABOVE))
-    {
-      DWORD exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
-
-      if (private->state & GDK_WINDOW_STATE_BELOW)
-        exstyle &= (~WS_EX_TOPMOST);
-      if (private->state & GDK_WINDOW_STATE_ABOVE)
-        exstyle |= WS_EX_TOPMOST;
-
-      API_CALL (SetWindowLong, (GDK_WINDOW_HWND (window), GWL_EXSTYLE, exstyle));
-    }
-
   if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
     {
       gdk_window_fullscreen (window);
@@ -1140,10 +1145,14 @@ show_window_internal (GdkWindow *window,
           if (focus_on_map && private->accept_focus)
            {
              SetForegroundWindow (GDK_WINDOW_HWND (window));
+             if (top == HWND_TOPMOST)
+               SetWindowPos (GDK_WINDOW_HWND (window), top,
+                             0, 0, 0, 0,
+                             SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
            }
          else
            {
-             SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOP,
+             SetWindowPos (GDK_WINDOW_HWND (window), top,
                            0, 0, 0, 0,
                            SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
            }